home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS04.ADF / C / inputdev.c < prev    next >
C/C++ Source or Header  |  1985-10-30  |  11KB  |  292 lines

  1. /* sample program for adding an input handler to the input stream */
  2.  
  3. /* note that this program also uses the CreateTimer, WaitTimer
  4.  * and DeleteTimer described in the timer device chapter.
  5.  *
  6.  * Rob Peck 10/1/85
  7.  */
  8. #define F1KEY 0x50
  9.  
  10. /* test program exits when the F1 key is touched.  Steals all input
  11.  * events from Intuition when the program is active.  Restores all
  12.  * to normal (including returning memory) when done 
  13.  */
  14.  
  15. #include <exec/types.h>
  16. #include <exec/ports.h>
  17. #include <exec/memory.h>
  18. #include <exec/io.h>
  19. #include <exec/tasks.h>
  20. #include <exec/interrupts.h>
  21. #include <devices/input.h>
  22. #include <devices/inputevent.h>
  23.  
  24. SHORT noticedEventClass;
  25.  
  26. struct Port *inputDevPort;
  27. struct IOStdReq *inputRequestBlock;
  28. struct Interrupt handlerStuff;
  29. struct InputEvent dummyEvent;
  30.  
  31. extern struct Port *CreatePort();
  32. extern struct IOStdReq *CreateStdIO();
  33.  
  34. struct MemEntry me[10];
  35.  
  36.         /* If we want the input handler itself to add anything to the
  37.          * input stream, we will have to keep track of any dynamically
  38.          * allocated memory so that we can later return it to the system.
  39.          * Other handlers can break any internal links the handler puts
  40.          * in before it passes the input events.
  41.          */
  42.  
  43. char **evString[] = { "NULL", "RAWKEY", "RAWMOUSE", "EVENT",
  44.                       "POINTERPOS", "UNDEFINED",  "TIMER", "GADGETDOWN", 
  45.                       "GADGETUP", "REQUESTER", "MENULIST", "CLOSEWINDOW", 
  46.                       "SIZEWINDOW", "REFRESHWINDOW", "NEWPREFS", "DISKREMOVED",
  47.                       "DISKINSERTED", "ACTIVEWINDOW", "INACTIVEWINDOW" };
  48. struct InputEvent 
  49. *myhandler(ev, mydata)
  50.         struct InputEvent *ev;  /* and a pointer to a list of events */
  51.         struct MemEntry *mydata[];  /* system will pass me a pointer to my 
  52.                                      * own data space.
  53.                                  */
  54. {
  55.         /* demo version of program simply reports input events as
  56.          * its sees them; passes them on unchanged.  Also, if there
  57.          * is a linked chain of input events, reports only the lead
  58.          * one in the chain, for simplicity.  
  59.          */
  60.         if(ev->ie_Class == IECLASS_TIMER) return(ev);
  61.         /* don't try to print timer events!!! they come every 1/10th sec. */
  62.  
  63.         if(ev->ie_Code == F1KEY) 
  64.                 noticedEventClass = F1KEY;  
  65.                 /* provide a means of exiting this program, by pressing F1 */
  66.         else 
  67.                 noticedEventClass = ev->ie_Class; 
  68.  
  69.         /* There will be lots and lots of events coming through here;
  70.          * rather than make the system slow down because something
  71.          * is busy printing the previous event, lets just print what
  72.          * we find is current, and if we miss a few, so be it.
  73.          * Normally this loop would "handle" the event or perhaps
  74.          * add a new one to the stream.  (At this level, the only
  75.          * events you should really be adding are mouse, rawkey or timer,
  76.          * because you are ahead of the intuition interpreter.)
  77.          * No printing is done in this loop (lets main() do it) because
  78.          * printf can't be done by anything less than a 'process'
  79.          */
  80.         return(&dummyEvent);    
  81.         /* pass on the pointer to the dummy event (most handlers would
  82.          * pass on a pointer to a changed or an unchanged stream) */
  83. }
  84.  
  85. extern struct Task *FindTask();
  86. struct Task *mytask;
  87. LONG mysignal;
  88. extern HandlerInterface();
  89.  
  90. struct IOStdReq *mytimerRequest;
  91. extern struct IOStdReq *CreateTimer();
  92. extern int WaitTimer();
  93. extern int DeleteTimer();
  94.  
  95. main()
  96. {
  97.         SHORT error;
  98.  
  99.         /* init dummy event, this is what we will feed to other handlers
  100.          * while this handler is active */
  101.         
  102.         dummyEvent.ie_Class = IECLASS_NULL; /* no event happened */
  103.         dummyEvent.ie_NextEvent = NULL; /* only this one in the chain */
  104.         
  105.         inputDevPort = CreatePort(0,0);         /* for input device */
  106.         if(inputDevPort == NULL) exit(-1);      /* error during createport */
  107.         inputRequestBlock = CreateStdIO(inputDevPort);     
  108.         if(inputRequestBlock == 0) { DeletePort(inputDevPort); exit(-2); }
  109.                                         /* error during createstdio */
  110.         mytimerRequest = CreateTimer();
  111.         if(mytimerRequest == NULL) exit(-3);
  112.  
  113.         handlerStuff.is_Data = &me[0];
  114.                         /* address of its data area */
  115.         handlerStuff.is_Code = HandlerInterface;
  116.                         /* address of entry point to handler */
  117.         handlerStuff.is_Node.ln_Pri = 51;
  118.                         /* set the priority one step higher than
  119.                          * Intution, so that our handler enters
  120.                          * the chain ahead of Intuition.
  121.                          */
  122.         error = OpenDevice("input.device",0,inputRequestBlock,0);
  123.         if(error == 0) printf("\nOpened the input device");
  124.  
  125.         inputRequestBlock->io_Command = IND_ADDHANDLER;
  126.         inputRequestBlock->io_Data = &handlerStuff;
  127.                 
  128.         DoIO(inputRequestBlock);
  129.  
  130.         for(;;)                 /* FOREVER */
  131.         {
  132.         WaitTimer(mytimerRequest, 0, 100000);   
  133.                         /* TRUE = wait; time = 1/10th second */
  134.         if(noticedEventClass == F1KEY) break;   /* exit from forever */
  135.         if(noticedEventClass != 0)
  136.                 {
  137.                 printf("\nJust noticed %s class of event",
  138.                                 evString[noticedEventClass]);
  139.                 noticedEventClass = 0;
  140.                 }
  141.         }
  142.         /* Although this task sleeps (main loop), the handler is independently
  143.          * called by the input device.
  144.          */
  145.  
  146.         /* Following are discussion purposes only, no way to get here.
  147.          * Would have to provide a way to wake up in order to exit.
  148.          */
  149.         inputRequestBlock->io_Command = IND_REMHANDLER;
  150.         inputRequestBlock->io_Data = &handlerStuff;
  151.         DoIO(inputRequestBlock);
  152.         CloseDevice(inputRequestBlock);
  153.         DeleteStdIO(inputRequestBlock);
  154.  
  155.         DeletePort(inputDevPort);
  156.         DeleteTimer(mytimerRequest);
  157. }                                       /* end of main */
  158.  
  159.  
  160. /* ******************************************************************** */ 
  161. /* Exec Support Functions:  CreateTimer, WaitTimer, DeleteTimer         */
  162. /*
  163. /* CreateTimer() returns a pointer to an IOStdReq structure, set up
  164.  * for communications with the timer device.  Returns NULL if it
  165.  * cannot allocate the timer or get enough memory or signals.
  166.  * 
  167.  * WaitTimer(IOStdReq,seconds,microseconds) uses the communications
  168.  * block from CreateTimer().  It puts your task to sleep until the
  169.  * timer counts down at least this amount of time.  
  170.  *
  171.  * SetTimer(IOStdReq,seconds,microseconds) returns a pointer to a port
  172.  * (copied from the IOStdReq) to which the timer returns the message
  173.  * block when the timeout has completed.  It uses SendIO to transmit
  174.  * the IORequest.  This means your task can go on to something else,
  175.  * then execute WaitPort(timerReplyPort), going to sleep until the
  176.  * timer has timed out.  You will still have to do a GetMsg(timerReplyPort)
  177.  * after your task awakens, where with WaitTimer this is not necessary.
  178.  *
  179.  * DeleteTimer(IOStdReq) uses the block from CreateTimer() to free up
  180.  * memory and signal bits that have been allocated for this purpose.
  181.  *
  182.  * syntax Summary:  struct IOStdReq *CreateTimer();
  183.  *                  int WaitTimer();
  184.  *                  struct Port *SetTimer();
  185.  *                  int DeleteTimer();
  186.  */
  187.  
  188.  
  189. #include <exec/types.h>
  190. #include <exec/lists.h>
  191. #include <exec/nodes.h>
  192. #include <exec/ports.h>
  193. #include <exec/io.h>
  194. #include <exec/devices.h>
  195. #include <devices/timer.h>
  196.  
  197. #define SECONDS io_Actual
  198. #define MICROSECONDS io_Length
  199. /* redefine fields in IOStdReq so as to match requirements of a timeval */
  200.  
  201.  
  202. extern struct Port *CreatePort();
  203. extern struct IOStdReq *CreateStdIO();
  204.  
  205. struct IOStdReq 
  206. *CreateTimer()          /* return a pointer to an IOStdReq if 
  207.                          * it was possible to allocate a new
  208.                          * timer */
  209. {
  210.         SHORT error;
  211.         struct Port *timerport;
  212.         struct IOStdReq *timermsg;
  213.         timerport = CreatePort(0,0);
  214.         if (timerport == NULL)
  215.                 return(NULL);  /* Error during CreatePort */
  216.         timermsg = CreateStdIO(timerport);
  217.         if (timermsg == NULL)
  218.                 {
  219.                 DeletePort(timerport);
  220.                 return(NULL);  /* Error during CreateStdIO */
  221.                 }
  222.         error = OpenDevice(TIMERNAME, UNIT_MICROHZ, timermsg, 0);
  223.         if (error != 0)
  224.                 {
  225.                 DeleteStdIO(timermsg);
  226.                 DeletePort(timerport);
  227.                 return(NULL);  /* Error during OpenDevice */
  228.                 }
  229.         return(timermsg);
  230. }
  231.  
  232. struct Port 
  233. *SetTimer(whichtimer,seconds,microseconds)
  234. ULONG seconds,microseconds;
  235. struct IOStdReq *whichtimer;
  236. {
  237.         struct Port *tempPort;
  238.         tempPort = whichtimer->io_Message.mn_ReplyPort;
  239.         whichtimer->io_Command = TR_ADDREQUEST;   /* add a new timer request */
  240.         whichtimer->SECONDS = seconds;            /* seconds */
  241.         whichtimer->MICROSECONDS = microseconds;  /* microseconds */
  242.         SendIO(whichtimer);
  243.         return(tempPort);
  244. }
  245.  
  246. int
  247. WaitTimer(whichtimer,seconds,microseconds)
  248. ULONG seconds,microseconds;
  249. struct IOStdReq *whichtimer;
  250. {
  251.         whichtimer->io_Command = TR_ADDREQUEST;   /* add a new timer request */
  252.         whichtimer->SECONDS = seconds;            /* seconds */
  253.         whichtimer->MICROSECONDS = microseconds;  /* microseconds */
  254.         DoIO(whichtimer);
  255.         return(0);
  256. }
  257.  
  258. int
  259. DeleteTimer(whichtimer)
  260. struct IOStdReq *whichtimer;
  261. {
  262.         struct Port *whichport;
  263.         whichport = whichtimer->io_Message.mn_ReplyPort;
  264.         DeleteStdIO(whichtimer);
  265.         DeletePort(whichport);
  266.         return(0);      
  267. }
  268.  
  269. *************************************************************************
  270. *   HandlerInterface()
  271. *
  272. *   This code is needed to convert the calling sequence performed by
  273. *   the input.task for the input stream management into something
  274. *   that a C program can understand.
  275. *
  276. *   This routine expects a pointer to an InputEvent in A0, a pointer
  277. *   to a data area in A1.  These values are transferred to the stack
  278. *   in the order that a C program would need to find them.  Since the
  279. *   actual handler is written in C, this works out fine. 
  280.  
  281.     XREF        _myhandler
  282.     XDEF        _HandlerInterface
  283.  
  284. _HandlerInterface:
  285.     MOVEM.L     A0/A1,-(A7)
  286.     JSR         _myhandler
  287.     ADDQ.L      #8,A7
  288.     RTS
  289.  
  290.     END
  291.  
  292.